package cn.tannn.surenessdemo.controller;

import cn.jdevelops.annotation.mapping.PathRestController;
import cn.jdevelops.exception.annotation.DisposeException;
import cn.jdevelops.result.result.ResultVO;
import cn.jdevelops.springs.service.url.UrlService;
import cn.jdevelops.springs.service.url.entity.MethodUrl;
import cn.jdevelops.springs.service.url.entity.Urls;
import cn.tannn.surenessdemo.constant.RoleConstant;
import cn.tannn.surenessdemo.controller.dto.AddAuthRoleDTO;
import cn.tannn.surenessdemo.sureness.annotation.ApiMapping;
import cn.tannn.surenessdemo.user.entity.AuthResource;
import cn.tannn.surenessdemo.user.service.AccountService;
import cn.tannn.surenessdemo.user.service.ResourceService;
import cn.tannn.surenessdemo.user.service.RoleService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.sql.SQLIntegrityConstraintViolationException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author tan
 * @date  2022.07.26 21点19分
 */
@PathRestController
@Slf4j
@Api(tags = "初始化管理", value = "初始化管理")
@RequiredArgsConstructor
@ApiSupport(order = 1)
public class InitController {

    /**
     * 资源
     */
    private final ResourceService resourceService;

    private final UrlService urlService;

    /**
     * 角色
     */
    private final RoleService roleService;

    /**
     * 用户
     */
    private final AccountService accountService;



    @ApiOperation(value = "初始化超管用户和基础角色", notes = "初始化管理")
    @ApiOperationSupport(order = 1)
    @ApiMapping(checkToken = false, value = "initBasics", method = RequestMethod.GET)
    @Transactional(rollbackFor = Exception.class)
    @DisposeException(messages = "请勿重复操作此接口",exceptions = SQLIntegrityConstraintViolationException.class)
    public ResultVO<String> initBasics() {
        roleService.addRole(AddAuthRoleDTO.builder()
                .code(RoleConstant.ADMINISTRATORS)
                .name(RoleConstant.ADMINISTRATORS)
                .description("超级管理员")
                .status(1)
                .build());
        roleService.addRole(AddAuthRoleDTO.builder()
                .code(RoleConstant.COMMON_USER)
                .name(RoleConstant.COMMON_USER)
                .description("放行一些不要权限但是需要登录的接口")
                .status(1)
                .build());
        roleService.addRole(AddAuthRoleDTO.builder()
                .code(RoleConstant.TEST_USER)
                .name(RoleConstant.TEST_USER)
                .description("测试用户")
                .status(1)
                .build());
        accountService.initUserAdmin("123");
        return ResultVO.success();
    }



    @ApiOperation(value = "新增当前项目所有接口到资源表(默认status=0)", notes = "初始化管理")
    @PostMapping("addResourceApi")
    @ApiOperationSupport(order = 3)
    public ResultVO<String> addResourceApi() {
        // 查询数据库已存在的资源 - 过滤掉
        Optional<List<AuthResource>> allResource = resourceService.getAllResource();
        List<MethodUrl> methodUrls = new ArrayList<>();
        if (allResource.isPresent()) {
            methodUrls = allResource.get().stream()
                    .map(authResource -> MethodUrl.builder()
                            .method(authResource.getMethod())
                            .uri(authResource.getUri())
                            .build())
                    .collect(Collectors.toList());
        }
        // 这个方法没有隐去注解放行的接口，但是无所谓了,后面在说把
        List<Urls> localUrl = urlService.getLocalUrl(methodUrls);
        List<AuthResource> authResources = new ArrayList<>();
        localUrl.forEach(it -> authResources.add(AuthResource.builder()
                .method(it.getRequestMethod())
                .description(it.getDescription())
                .name(it.getDescription())
                .status(0)
                .uri(it.getUrl())
                .type(it.getGrouping())
                .build()
        ));
        if (resourceService.addResource(authResources)) {
            if (log.isDebugEnabled()) {
                log.debug("add resource success: {}", authResources);
            }
            return ResultVO.success();
        } else {
            return ResultVO.fail("资源已存在");
        }
    }


    @ApiOperation(value = "给超级管理员角色初始化资源（code=admin,同时将所有接口都置为拦截）", notes = "初始化管理")
    @PostMapping("addRoleResource")
    @ApiOperationSupport(order = 4)
    public ResultVO<String> addRoleResource() {
        Optional<List<AuthResource>> allResource = resourceService.getAllResource();
        if(allResource.isPresent()){
            roleService.authorityRoleResource(RoleConstant.ADMINISTRATORS,
                    allResource.get().stream().map(AuthResource::getCode)
                            .collect(Collectors.toList()));
            resourceService.interceptAll();
            return ResultVO.success();
        }else {
            return ResultVO.fail("暂未资源添加，请先添加资源");
        }
    }
}
